Beginners Programming
Beginning Game Programming
Session 4
Great Games in Liberty BASIC
For Liberty BASIC versions 2 and 3
© Richard G. Ryles, August 2003,
Email: rryles@jeff-davis.k12.ga.us
Web: http://jdexchange.jeff-davis.k12.ga.us/~rryles/
Introduction
If you would like to see my solutions to the problems I left you with, load up and run, in Liberty BASIC, SG3sol.bas and SC3sol.bas. If you are not sure about what’s happening refer to the notes that I have made in the code. I preceded the solutions with ‘***Solution Code ****. If you have any questions e-mail me or post your question on the message board under the “Game Programming” topic.
This month we are going to add explosions, break-ups and random locations to our games. I stated last month that we would look at adding MIDI files to our game but I’ve decided to wait until next time on that. If you really need to know about adding music to your game before next month then again e-mail me or post your question on the LB Conforums board.
Once again, this article is divided into two different sections. The first is going to deal with the sub game and the second with the shooting gallery game. Also, this way if you are only interested in one of the games it will be easier to tell the two apart (there are some aspects covered in each game that are not covered in the other).
I’ve attempted to keep the file names to eight characters or less, so that those using LB version 2 will not have a problem loading the included files.
Also, with this session, I will not be showing you as many actual screenshots as in previous sessions. By now you should have a good idea of where everything goes and be familiar with the program structure. If you are just starting with this session I suggest that you download the newsletters (issues 109, 110, and 111) with the previous sessions in them and start from the beginning.
Let’s get started.
Sub Command Game
What We Hope to Accomplish
First we will deal with explosions and secondly we will deal with the sinking of our collided entities. In this session we will cause our ship and our good sub to explode when hit. We will then work on them sinking. I’ve noticed in my game files that somewhere along the way I gave the enemy sub the ability randomize its beginning Y location, we will discuss this also this session.
Explosion Demonstration
Open the file in the file section called explo.bas. The explosion graphics we will be using are made by Ari Feldman ari@arifeldman.com. He does a much better job than I with graphics. Check out his site for more graphics that you may use. Also notice that I have given him credit for using his graphics. You need to make sure that you give others credit for graphics or code you use that is not your own. If you don’t know to whom it belongs then state that.
The explosion is actually made up of five separate bitmaps but we cycle them to make it look more realistic. Run the explo.bas file and see what I’m talking about. I’ve placed the explosion in the upper left corner. The blue area represents the actual window in a game and the black sides represent “off screen” locations. In the game we will place the explosion off the screen where it cannot be seen until we move it to the viewing area. The mine is attached to the cursor and the sub is in the middle of the screen. When the mine contacts the sub the sub is replaced by the explosion graphic and we move the sub out of view. Once the explosion has cycled (exploCount) the number of designated times we move the explosion off the viewing area the sub back.
Pay particular attention to the notes in the [count] and [CheckCollision] branches. The explosion cannot happen unless exploActive is equal to zero. The 20 timer cycles lets the explosion stay on the screen for about two seconds. You can change this number to increase or decrease the amount of time that the explosion is on the screen. At this point step back and notice the if/then branches. These determine if and when an explosion will take place. See if you can trace what is happening with them.
The Exploding Ship
Load your SubCom3 game or the SC3sol.bas and save it as SubCom4.bas.
Load the five explosion bitmaps into memory using the loadbmp command.
Now under Section III add the following two variables:
exploCount=0 exploActive=0
Section IV B.
print #game.g, "addsprite explo explo1 explo2 explo3 explo4 explo5"
Now under Section IV C place the following code:
print #game.g, "spritexy explo 700 700"
Section IV D. Set other Sprite Attributes
print #game.g, "cyclesprite explo 1"
In Section VIII unload the explosion bitmaps:
unloadbmp "explo1"
unloadbmp "explo2"
unloadbmp "explo3"
unloadbmp "explo4"
unloadbmp "explo5"
Under Section VII Timer Branch add the following code:
gosub [count]
Under Section X add the following:
[count]
if exploActive = 1 then exploCount=exploCount+1
if exploCount>20 then
exploActive=0 'resets the exploActive variable
exploCount=0 'resets the exploCount variable
print #game.g, "spritexy explo 700 700"
end if
return
In the [TorpShipCollision] branch, after the following two lines
print #game.g, "spritecollides torpedo list$"
if list$= "ship" then
if exploActive=0 then print #game.g, “spritexy? torpedo torpedoX torpedoY”; print #game.g, "spritexy explo "; torpedoX-25; " " ;torpedoY-25 exploActive = 1 end if
All we have done so far is copy the code from the Explosion demonstration program into our SubCom program. If you don’t understand anything go back to the explo.bas program and look at the comments.
Sinking the Ship
Causing the ship to sink is not too difficult. We just replace the ship sprite with a broken ship sprite and make it move in a positive Y direction. Well, maybe there is a little more to it than that but let’s add the code into your program and discuss how it all works.
First, in Section II, load the three sinking ship bitmaps into memory, they are called sinkship1, sinkship2 and sinkship3. It also would not be a bad idea at this time to place the unloadbmp code for each bitmap in Section VIII before you forget.
Now in Section IV B add the following code:
print #game.g, "addsprite shipsinking shipsinking1 shipsinking2 shipsinking3";
Under Section IV C locate the shipsinking sprite off screen, I used 600 600.
Under Section IV D, scale the sinking ship to 75 and set it to cycle.
Now in Section VII add the following branch label:
gosub [CheckSinkingShip]
This will check to see if the sinking ship has gone off the bottom of the screen
Then modify the [TorpShipCollision] branch to look like the following bit of code:
[TorpShipCollision]
print #game.g, "spritecollides torpedo list$"
if list$= "ship" then
if exploActive=0 then
print #game.g, "spritexy? torpedo torpedoX torpedoY";
print #game.g, "spritexy? ship shipX shipY"; ‘locates the ship
print #game.g, "spritexy explo "; torpedoX-25; " " ;torpedoY-25
print #game.g, "spritexy shipsinking "; shipX; " " ;shipY ‘places the sinking ship where the ship is at
print #game.g, "spritemovexy shipsinking 0 3";
exploActive = 1
end if
print #game.g, "spritexy ship ";-100;" ";sy 'moves the ship off the screen
print #game.g, "spritemovexy ship 0 0"; 'Stops the ship movement
torpedoX=150:torpedoY=300 'move torpedo off the screen
TorpFlag=0 'says that there is no active torpedo
score=score+1
playwave "boom.wav", async
end if
return
In the above code with the “spritexy?” we are getting the locations of the torpedo and the ship. We then place the explosion at the torpedo’s location and the sinking ship at the ships location. The spritemovexy shipsinking 0 3 causes the sinking ship to move down at a rate of three pixels per timer cycle. After we have located the ship off the screen we stop it from moving with the spritemovexy ship 0 0 command. We will start if moving again later after the sinking ship has moved off the bottom of the screen.
Immediately after that add in this new branch:
[CheckSinkingShip]
print #game.g, "spritexy? shipsinking sinkingX sinkingY"; 'get the location of the sinking ship
if sinkingY>300 then 'check the location of the sinking ship
print #game.g, "spritemovexy ship -5 0" 'start the ship moving again
print #game.g, "spritemovexy shipsinking 0 0" 'stop the sinking ship from moving
end if
return
Here we are checking the Y location of the sinking ship. If the Y location is greater than 300, no longer on the screen then we start our ship moving again and stop the sinking ship from moving. Aren’t if/then statements wonderful?
Now save your work and run your program. When the torpedo hits the ship the explosion should come up in the ship’s place and the sinking ship should begin to sink. Once the sinking ship has gone off the bottom of the screen the ship should begin again from the right edge.
Another Explosion?
Now you may ask, what if I want more than one explosion to be happening at one time? Well, I can answer that question for you. It is a matter of setting up another explosion. You will pretty much copy the same code except maybe name it explo2. Let’s set this up now for the sub, whether a mine hits it or the enemy sub.
First under Section III we need to initialize the variables for this new explosion. Add the following lines to the end of Section III:
exploCount2=0 exploActive2=0
In Section IV B copy and pasted the addsprite code for the first explosion and then renamed it as “explo2”:
print #game.g, "addsprite explo2 explo1 explo2 explo3 explo4 explo5";
Then under Secion IVC copy and paste the code for the initial location of the new exposion from the first explosion. Then rename it to “explo2” and set it’s X and Y to 800:
print #game.g, "spritexy explo2 800 800";
Down in Section IV D set the “explo2” sprite to cycle:
print #game.g, "cyclesprite explo2 1"
At this point I am only going to walk you through setting this up to happen when the mine and sub collide. From there you will be able to apply this to any other collision that you would like.
Under the [MineSubCollision] branch, change the first part to look like the code below. Pay attention to the comments in the code, these will explain the code. The newest item is the “spritevisible” command. If you would like more information on this look it up in the help file.
[MineSubCollision]
print #game.g, "spritecollides mine list$"
if list$="sub" then
if exploActive2=0 then 'let's the below only happen if explo2 is not on the screen
print #game.g, "spritexy? mine mineX mineY"
print #game.g, "spritexy explo2 ";mineX;" ";mineY
print #game.g, "spritevisible sub off" 'Hides the sub from view
subNum=subNum-1 'subtracts one from our lives
mineY=350 'puts the mine in a position to start over
playwave "boom.wav", async
print #game.g, "spritexy mine ";mineX;" ";mineY
exploActive2=1 'says that explo2 is on the screen
end if
end if
Before the “return” in the [count] branch add the following lines. This is simply a copying of the code before it with the names changed to reflect the second explosion. Sub visibility is also turned back on and placed in the middle.
if exploActive2=1 then exploCount2=exploCount2+1
if exploCount2>20 then
exploActive2=0
exploCount2=0
sx=200:sy=135 'places the sub in the middle of the playing area
print #game.g, "spritexy explo2 800 800" 'moves explo2 back off the screen
print #game.g, "spritexy sub ";sx;" ";sy
print #game.g, "spritevisible sub on" 'makes the sub visible again
end if
Save your work and run the program. Now when the sub hits the mine it should go away and be replaced by the explosion. When the explosion is finished cycling it will disappear and the sub will be placed back into the middle of the playing area.
Random Y Locations
I had not planned on covering random Y locations until this month but I see that I covered it last month but forgot to include it in the menu. I’m including last month’s discussion here for any that may have missed it or need a refresher.
Last month’s discussion -------------
Let’s add some variation to our enemy sub. Just a little bit of code will do it.
[TrapEnemy]
print #game.g, "spritexy? enemy enemyX enemyY"
if enemyX>500 then
enemyY=int(rnd(0)*180)+55
print #game.g, "spritexy enemy ";0;" ";enemyY
end if
return
Modify your TrapEnemy branch. The line that says enemyY=int(rnd(0)*180)+55 gives us a random number between the numbers 55 and 234, the Y range that we want the enemy sub to move around in. Let’s try to break this down. rnd(0) gives us a number between 0 and 1. Since we want a range of 180 numbers we multiply that value by 180. Our answer will have several numbers to the right of the decimal that we don’t want so we place the int function at the beginning. This drops all numbers to the right of the decimal. Next, I don’t want the number to be less than 55 so I add 55 to my random generated number. Now the next line simply tells the program to place the sprite in it’s new location which is zero in X and the randomly generated number in Y. English please… Each time we relocate the enemy sub to the left of the screen it is given a new Y location. So, it will appear in a different Y location each time it restarts.
If you need more information on rnd and int go to the help menu and look them up. If you’re still confused email me.
Again, save your work and test it. You should notice the enemy sub starting in a new Y location each time it restarts on the left side.
End of discussion -----
SubCommand Challenges for this Month
This month your challenges for the SubCommand Game will be as follows:
Final Remarks on SubCommand
As you can see we’ve go quite a bit of code here. I have over 325 lines of it. Next session we will have our ship drop multiple mines and let our sub shoot horizontal torpedoes as well as multiple torpedoes. We will also add some music to our games.
The Shooting Gallery Game
Our Objectives for This Session
We are going to look at manipulating graphics at the point of collision. More specifically, we are going to cause the balloon to pop and fall and the squirrel to jump and fall when they are hit. We will then move on to causing the target to drop at random X when it restarts at Y0.
Balloon Pop Example
Open up Bpop.bas from the included files. Run the program and see what it does. Stop the program and let’s take a look at the new things it has.
[collision]
print #w.g, "spritecollides bullet list$"
if list$="balloon" then
print #w.g, "spritexy balloon 0 200" 'move balloon out of the way, off screen normally
print #w.g, "spritexy BFall 135 5" 'place the deflated balloon where the other ballon was
print #w.g, "spritemovexy BFall 0 10" 'automove the deflated balloon downward at a rate of ten pixels per timer cycle
end if
return
In the [collision] branch when we have a collision we move the balloon to another location, usually off screen and put the deflated balloon in it’s location. In our program we will get the location of the balloon with the “spritexy?” command. Then we set the deflated balloon to automove downward at a rate of ten pixels per timer cycle.
[CheckBFall]
print #w.g, "spritexy? BFall bfX bfY" 'see where the deflated balloon is at
if bfY>270 then 'if it has fallen past 270 in Y then do the following
print #w.g, "spritemovexy BFall 0 0" 'stop automove
print #w.g, "spritexy balloon 135 5" 'return to beginning locationn
print #w.g, "spritexy BFall 260 5" 'return to beginning location
end if
return
In the [CheckBFall] branch we are watching to see when the deflated balloon goes off the bottom of the screen. Once it has gone past 170 we stop the automove with 0 0 and return both sprites back to their beginning locations. In a program the beginning location for the deflated balloon is usually off screen.
Popping the Balloon
Now open up your SGallery2.bas file or my SG2sol.bas. Let’s save it under a different name. Go to File>>Save As… and give this file the name of SGallery3.bas.
We are now going to insert the deflated balloon falling routine into our program.
Load the two deflated balloon bitmaps into memory under Section II:
loadbmp "BFall1", "BFall1.bmp" loadbmp "BFall2", "BFall2.bmp"
Next add the BFall sprite to the current window in Section IV B:
print #game.g, "addsprite BFall BFall1 BFall2"
Under Section IV C set the initial location of the Bfall sprite:
print #game.g, "spritexy BFall -100 -100";
Then, under Section IV D set the following attributes for Bfall:
print #game.g, "cyclesprite BFall 1"
print #game.g, "spritescale BFall 50"
Now go do to your [CheckCollisions] branch and everywhere you have the word “balloon” in a collision list add the following code inside of the if/then statement:
print #game.g, "spritexy? balloon bfX bfY";
print #game.g, "spritexy balloon -200 -200" 'move balloon out of the way, off screen
print #game.g, "spritexy BFall ";bfX;" ";bfY 'place the deflated balloon where the other ballon was
print #game.g, "spritemovexy BFall 0 10" 'start the deflated balloon falling
print #game.g, "spritemovexy balloon 0 0" 'stop the balloon from going up
Go back up to Section VII and add in the following gosub:
gosub [CheckBFall]
Drop down to just above your [quit] branch and add the [CheckBFall] branch into your code:
[CheckBFall]
print #game.g, "spritexy? BFall bfX bfY" 'see where the deflated balloon is at
if bfY>270 then 'if it has fallen past 270 in Y then do the following
print #game.g, "spritemovexy BFall 0 0" 'stop automove
print #game.g, "spritemovexy balloon 4 -5" 'starts balloon moving again
print #game.g, "spritexy balloon ";balloonX;" ";balloonY 'returns balloon to beginning location
print #game.g, "spritexy BFall -100 -100" 'return to beginning location
end if
return
Save and run your program. When you shoot the balloon, the falling deflated balloon should replace it. If not, check your typing. If the deflated balloon falls down in front of the bottom board, then go back to Section IV B and make sure you added the deflated balloon before the board.
Make the Squirrel do a Flip and Fall
I want to make the squirrel jump up, flip and fall. We will need to modify several sections of code in order to do this.
First we will need a new variable to tell us when the squirrel has been shot and is in the process of falling. Under Section III add the variable squirrelShot=0.
Now go down to Section IVB and cut and paste the print #game.g, "addsprite squirrel squirrel1 squirrel2"; section of code after where you have added the board. This will cause the squirrel sprite to be in front of the board sprites so that when the squirrel falls it will pass in front of the board instead of behind.
Click on the Jump To... button on the LB icon bar and double click on the [CheckCollisions] branch. Modify your code so that the part that checks for a collision with the squirrel looks like the code below.
[CheckCollisions]
print #game.g, "spritecollides bullet list$"
if squirrelShot=0 then **New Line
if list$= "squirrel sight" or list$= "squirrel board sight" then
squirrelShot=1 **New Line
print #game.g, "spritexy? squirrel squirrelX squirrelY" ***New Line
print #game.g, "spritexy squirrel ";squirrelX;" ";squirrelY-10 ***New Line
if list$="squirrel sight" then Score=Score+1
if list$="squirrel board sight" then Score=Score+1
end if
end if
if squirrelShot=1 then gosub [SquirrelFall] ***New Line
The line above that has squirrelY-10 is what causes the squirrel to jump up.
Now, go to the end of your file and add the [SquirrelFall] branch:
[SquirrelFall] print #game.g, "spriteorient squirrel flip" print #game.g, "spritemovexy squirrel 0 10" print #game.g, "spritexy? squirrel squirrelX squirrelY" if squirrelY>300 then print #game.g, "spritexy squirrel 300 205" print #game.g, "spriteorient squirrel normal" print #game.g, "spritemovexy squirrel -4 0" squirrelShot=0 end if return
Flip, flips the squirrel over onto its back.
We then reset spritemovexy to cause the squirrel to move down 10 pixels each drawframe. We then check its location each time with spritexy? If its Y is greater than 300 then we move the squirrel back to its initial location, orient it to normal and reset its spritemovexy back to what it was originally.
That was not too hard was it? I hope that you will be able to adapt this and use it someway in some of your games.
Be sure to save your work.
Random Target X Locations
With our SubCom program we caused the enemy to restart in random Y locations. With our Sgallery program we will be causing the target to restart in random X locations.
[TrapTarget] 'tapping routine for target
print #game.g, "spritexy? target targetX targetY"
if targetY>244 then
targetX=int(rnd(0)*270)+5
print #game.g, "spritexy target ";targetX;" ";0
end if
return
Modify your [TrapTarget] branch to look like that above. The line that says targetX=int(rnd(0)*270)+5 gives us a random number between the numbers 5 and 275, the range that we want the target to move around in. Let’s try to break this down. rnd(0) gives us a number between 0 and .99999…. Since we want a range of 270 numbers we multiply that value by 270. Our answer will have several numbers to the right of the decimal that we don’t want so we place the int function at the beginning. This drops all numbers to the right of the decimal. Next, I don’t want the number to be less than 5 so I add 5 to my random generated number. Now the next line simply tells the program to place the sprite in it’s new location which is the randomly generated number in X and 0 in Y. English please… Each time we relocate the target to the top of the screen it is given a new location. So, it will appear in a different location each time it restarts.
A little tidbit of information here: if you will notice that in the [CheckCollisions] branch I set the target to be relocated at Y 300 each time the target was hit. This caused the [TrapTarget] routine to relocate the sprite for me without me having to add in additional code to relocate the sprite in the [CheckCollisions] branch. – saves space and time.
If you need more information on rnd and int go to the help menu and look them up. Here is a little program you can copy and run to see exactly what rnd(0) is giving us:
for i = 1 to 100 print rnd(0) next i
If you’re still confused email me.
Again, save your work and test it. You should notice the target starting in a new X location each time it restarts at the top.
Shooting Gallery Challenges for this Month
This month your challenges for the Shooting Gallery Game will be as follows:
1. Set up duck and duck2 to be relocated in random Y locations. Refer to the SubCom section on Random Y locations.
2. Using the included tbreak.bmp included set up the target to break and fall when hit.
3. Load and add in a new duck sprite called duckred.bmp. Choose one of your ducks to change between the yellow duck and this red duck each time hit.
4. Add different wav sounds to each entity as it is hit. Just stick this code (playwave "shot", async) into the program where you want the sound to happen at, replace shot with the name of your wave. If you wanted to use the boom.wav you would replace shot with boom.
Closing Remarks
Sorry it took me so long to get this article out. As you can see from your own games, these game articles are getting fairly large. This makes for slightly more tedious work here plus at the moment, with the start of a new school year, I don't have as much time to devote to LB as I would like. Next time we will definitely take a look at adding MIDI files to your game, see NASA's Sub Hunter game for an example. We will also work with multiple torpedoes, mines, targets and ducks. And if I'm able to get it in we will sometime in the future deal with entities that appear randomly on the screen, stay for a few seconds and then disappear.
Until then: Happy Programming!